#ifndef _POLY_LIB_H
#define _POLY_LIB_H

#include "matlib.h"

#define BAD_SAMPLE -1  /* for marking bad depth sample */

typedef struct DepthSample {
	float value;
	int id;  /* polygon ID, mostly for debugging */
	struct DepthSample *next;
} DepthSample;

typedef struct DepthBuffer {
	int xsize,ysize,zsize;
	float xdelta,ydelta,zdelta;
	gtMatrix mat,imat;
	DepthSample **depths;
} DepthBuffer;



#define  BOX_FILTER       1
#define  TENT_FILTER      2
#define  GAUSSIAN_FILTER  3
#define NUM_ATTRIBS 6     /* number of interpolated attributes per gtVertex */
#define FIRST(vert) (&((vert)->x))  /* pointer to first attribute of gtVertex */

typedef struct gtVertex {
	float x,y,z;
	float ex,ey,ez;
} gtVertex;

typedef struct Edge {
	gtVertex point;   /* current position, color, etc. */
	gtVertex delta;   /* change in position, etc., between pixels or scanlines */
	float ymax;       /* maximum y value of the edge */
} Edge;

typedef struct gtPolygon {

	gtVertex **verts;
	int *iverts;
	int num_verts;

	int id;  /* polygon ID, mostly for debugging */

	gtVertex *clip_verts;
	int num_clip_verts;

	float ymin;
	int ileft,iright;
	Edge left,right;
	int edges_remaining;
	unsigned char draw_flag;

	struct gtPolygon *next;

} gtPolygon;

typedef unsigned char	BYTE;	



class GregVoxelizer
{
public:
	GregVoxelizer(gtSimulator* gt);
	~GregVoxelizer();
	void gtRenderScene(char *volume_name, int nbuffs);
    void SetGeomtryInfo(gtVertex** polyVerts, int numVerts, gtPolygon** polygons, int numPolys);
	void SetParamsAndOutput(int xSize, int ySize, int zSize, double volMinX, double volMinY, double volMinZ, double volMaxX, double volMaxY, double volMaxZ, BYTE*** solidElements);
private:
	unsigned char*** mOutput;
	gtSimulator* gtSim;
	/* local variables */

	gtVertex **poly_verts;       /* vertex list */
	int global_num_verts;
	int current_num_verts;
	int global_max_verts;

	gtPolygon **polys;    /* list of polygons */
	int num_polys;
	int max_polys;

	int filter_type;
	int filter_radius;
	float std_dev;
	int voxel_size;
	int supersample;
	int voxel_pad;
	int pgm_header;     
	int ray_stab;
	float double_surface_dist;
	int voxel_y_size;
	int voxel_z_size;
	double vol_x_max, vol_x_min, vol_y_max, vol_y_min, vol_z_max, vol_z_min;

	gtVertex clip_verts1[9000];
	gtVertex clip_verts2[9000];


	float *zbuffer;            /* depth for performing hidden surfaces */
	int zbuffer_enabled;   /* are we z-buffering? */

	int xsize,ysize;  /* size of framebuffer and z-buffer */
	DepthBuffer *current_depth_buffer;
	gtPolygon *global_poly;

	int draw_surfaces;  /* draw the depth buffer? */

	void vertex_copy (gtVertex *, gtVertex *);
	void polygon_setup();
	void setup_edge (Edge *, float, int, int, gtPolygon *);
	void fill_scanline (float, Edge *, Edge *);
	void render_span(gtPolygon *, float);

	void polygon_vol_setup(gtPolygon *,DepthBuffer *);
	int convexity_test (gtPolygon *poly, int iv);
	int inside_volume(DepthBuffer *depth_buffer, float x, float y, float z);
	void write_slice(int xsize,	int ysize,	unsigned char *slice_data,	char *volume_name, int slice_num);
	void voxel_filter(unsigned char **slices, int xs, int zs, int supersample, int filter_radius, float *filtered);
	void write_volume(DepthBuffer **buffers, int num_buffers, char *volume_name);
	void trans_from_size(DepthBuffer *d, int decision, float delta);
	void scan_volume(DepthBuffer *dbuffer);
	DepthBuffer ** three_buffers();
	DepthBuffer ** many_buffers();
};

#endif